package com.nulldev.util.concurrency.threadIt.v4.executors.fje.utils;

import java.util.Iterator;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

import com.nulldev.util.VariableAPI.ArrayUtils;
import com.nulldev.util.concurrency.threadIt.v4.executors.fje.interfaces.ThreadPicker;
import com.nulldev.util.data.Variables;

public class RoundRobinThreadPicker<T extends Thread> implements ThreadPicker<T> {
	private final CyclicalListIterator<T> iterator;

	public RoundRobinThreadPicker(final List<T> threads) {
		this.iterator = new CyclicalListIterator<T>(Variables.requireNonNullObject(threads, "threads"));
	}

	@Override
	public T nextThread() {
		return this.iterator.next();
	}

//	@Override
//	public List<T> nextThreads(int size) {
//		return this.iterator.nextN(size);
//	}

	static class CyclicalListIterator<T> implements Iterator<T> {
		private final List<T> list;
		private final AtomicInteger index = new AtomicInteger(0);

		public CyclicalListIterator(final List<T> collection) {
			this.list = collection;
		}

		@Override
		public boolean hasNext() {
			return !list.isEmpty();
		}

		@Override
		public T next() {
			try {
				final T ret = list.get(index.get());
				index.lazySet((index.get() + 1) % list.size());
				return ret;
			} catch (Exception e) {
				System.out.println(e);
				return ArrayUtils.random(this.list);
			}
		}

		public List<T> nextN(final int n) {
			return list.subList(index.get(), index.updateAndGet((e) -> {
				return (index.get() + n) % list.size();
			}));
		}

		@Override
		public void remove() {
			throw new UnsupportedOperationException();
		}
	}
}